home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1999 March
/
EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso
/
earcd
/
devel
/
vbcc-68k-src
/
machines
/
amiga68k
/
libsrc
/
alib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-01-01
|
16KB
|
550 lines
/*
* ALIB Rev. 1.0
* Amiga Object Module Librarian
* Programmed by Mike Schwartz
* (C)1985, MS Software, all rights reserved.
*
* Feel free to distribute this program on a no-charge basis.
*
* Use:
* ALIB option library filelist
* Where
* option may be one of the following:
* D = delete object modules from library
* R = replace object modules (or add if not defined)
* L = directory of library
* library is the name of the library file to be created or modified.
* if no .lib extension is provided on the command line, it is
* appended. Also note that a file library.dir is created for
* each library file and is managed by this program.
* filelist is a list of object module filenames separated by spaces
* or commas. Note that if .o is not present in the filenames,
* .o will be appended.
*/
/* This version of Alib has been modified, without permission, by
* Stephen Williams. Changes are as follows:
*
* - .o is now not unconditionally added to object file names. If the
* extension is already present, no action is taken. This appears to
* be how the author wished Alib to behave (check out the online help)
* but it never worked for me;
*
* - .lib may be added to the library name on the command line. If it
* isn't, it will be added. .dir is handled fairly intelligently.
* Again, the online help advertised this feature, although it never
* worked;
*
* - Unix-style I/O (open(), close(), read() etc) has been replaced with
* ANSI-style stdio streaming (fopen(), fclose(), fread() etc) to aid
* portability, and generally make my life easier;
*
* - errors now go to stderr instead of stdout (I didn't bother marking
* each individual change);
*
* - all files are written with permissions ----rw-d;
*
* - lots of little changes (marked where they have been made)
*/
static const char DOLLARVER[] = "\0$VER: Alib 1.0sw1 (11.3.98)";
/* #include lines modified by Stephen Williams */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef AMIGA
#include <dos/dos.h>
#include <clib/dos_protos.h>
#include <inline/dos_protos.h>
extern void * DOSBase;
#endif
/*
* The following structure defines the records in the .dir file for
* the library.
*/
#define LD struct libdir_def
struct libdir_def {
char object_filename[80]; /* name of .o file */
long module_offset; /* offset of module in .lib file */
long module_size; /* size of module in bytes */
};
/*
* When the library is openned, each object module is read into memory
* and managed with the following structure.
*/
#define LL struct liblist_def
struct liblist_def {
struct libdir_def dir_entry; /* directory entry for module */
char *object_module; /* actual text of module */
LL *next; /* pointer to next in list */
};
/*
* +++ Change by Stephen Williams +++
*
* The original source here defined prototypes for external functions
* getmem() and lseek(). lseek() hasn't been used in my altered source;
* I replaced it with the stdio stream equivalent fseek(). getmem(),
* along with rlsmem(), is not defined anywhere in my includes, so I
* have provided macros to emulate these functions
*/
#define getmem(size) (char *)calloc(size, 1)
#define rlsmem(pointer, size) free(pointer)
/*
* +++ Addition by Stephen Williams +++
*
* The original source just strcat()ed a ".o" onto the end of all
* object file names. This has been replaced with the following
* macro, which only adds .o if it isn't there already
*/
#define makeobjname(s) if(strcmp((char *)(s + strlen(s) - 2), ".o")) strcat(s, ".o")
/*
* Global variables
*
* +++ Changes by Stephen Williams +++
*
* "int libfd", "int objfd" and "int dirfd" have become
* "FILE * libfp", "FILE * objfp" and "FILE * dirfp"
* to reflect the changes from Unix-style I/O to stdio streams
*/
LL * objlist=NULL; /* linked list of object modules */
char libname[80]; /* name of library file */
FILE * libfp; /* file pointer for library file */
char objname[80]; /* name of object file */
FILE * objfp; /* file pointer for object file */
char dirname[80]; /* name of directory file */
FILE * dirfp; /* file pointer for directory file */
char buf[512]; /* misc buffer */
char option; /* user selected option */
/*
* This function prints the help messages and exits.
*
* K&R-style function definition changed to ANSI-style by Stephen Williams
*/
void help(void)
{
/*
* +++ Changes by Stephen Williams +++
*
* - Multiple printf() statements merged into one;
* - Help text reworded
*/
printf("Use:\n"
" Alib D <library[.lib]> <object[.o]> [object[.o] ...]\n"
" Alib R <library[.lib]> <object[.o]> [object[.o] ...]\n"
" Alib L <library[.lib]>\n\n"
"Where\n"
" D = delete object modules from library\n"
" R = replace object modules (or add if not defined) \n"
" L = directory of library\n\n"
" Note that a file \"library.dir\" is created for each library file,\n"
" and is managed by this program. If \".lib\" and/or \".o\" suffixes\n"
" are omitted on the command line, they will be added by the program.\n");
exit(1);
}
/*
* The following function opens the library and directory file. If the
* file does not exist, then the user is asked if he wants to create it.
* If the library exists, then it is read in and built in a linked list.
*
* K&R-style function definition changed to ANSI-style by Stephen Williams
*/
int open_library(void)
{
LL *lp; /* pointer to module node */
/*
* Open the library file and directory file.
* Changed by Stephen Williams to use stdio streams
*
*/
libfp = fopen(libname, "r");
if (!libfp) {
/*
* Library does not exist, prompt user for creation.
*/
while (1) {
printf("%s does not exist, create it? (Y/N): ", libname);
gets(buf);
if (buf[0] == 'y' || buf[0] == 'Y')
return !0;
if (buf[0] == 'n' || buf[0] == 'N') {
fprintf(stderr, "Alib abandoned\n");
exit(1);
}
}
}
dirfp = fopen(dirname, "r");
if (!dirfp) {
fprintf(stderr, "%s has been corrupted\n", dirname);
fprintf(stderr, "Alib abandoned\n");
exit(1);
}
/*
* library and directory files are open, read in the library.
*/
while (1) {
/*
* Allocate a node to hold the object module.
*/
lp = (LL *)getmem(sizeof(LL));
if (lp == NULL) {
fprintf(stderr, "Not enough memory.\nAlib abandoned\n");
exit(1);
}
/*
* Check for end of file.
*/
if (fread(&lp->dir_entry, sizeof(LD), 1, dirfp) != 1)
break;
/*
* Allocate a buffer to hold the object file image.
*/
lp->object_module = getmem(lp->dir_entry.module_size);
if (lp->object_module == NULL) {
fprintf(stderr, "Not enough memory.\nAlib abandoned\n");
exit(1);
}
/*
* Read in the object module
*/
if (fread(lp->object_module, lp->dir_entry.module_size, 1, libfp) !=
1) {
fprintf(stderr, "Library file is corrupted.\nAlib abandoned\n");
exit(1);
}
/*
* Add module to linked list.
*/
lp->next = objlist;
objlist = lp;
}
/*
* Library has been read in ok. Close files and return.
*/
fclose(libfp);
fclose(dirfp);
printf("Library file read in ok\n");
}
/*
* The following function removes an object module from the linked list
* and frees up any memory used by it.
*
* K&R-style function definition changed to ANSI-style by Stephen Williams
*/
int kill_module(char * name)
{
LL *lp;
LL *lp2;
if (objlist == NULL)
return 0;
strcpy(objname, name);
/*
* the next line changed from
* strcat(objname, ".o");
* by Stephen Williams
*/
makeobjname(objname);
if (strcmp(objlist->dir_entry.object_filename, objname) == 0) {
lp = objlist->next;
rlsmem(objlist->object_module, objlist->dir_entry.module_size);
rlsmem((char *)objlist, sizeof(LL));
objlist = lp;
return !0;
}
for (lp = objlist; lp->next != NULL; lp=lp->next)
if (strcmp(lp->next->dir_entry.object_filename, objname) == 0) {
lp2 = lp->next;
lp->next = lp2->next;
rlsmem(lp2->object_module, lp2->dir_entry.module_size);
rlsmem((char *)lp2, sizeof(LL));
return !0;
}
return 0;
}
/*
* K&R-style function definition changed to ANSI-style by Stephen Williams
*/
void add_module(char * name)
{
LL *lp;
int len;
strcpy(objname, name);
/*
* the next line changed from
* strcat(objname, ".o");
* by Stephen Williams
*/
makeobjname(objname);
/* Initial \n in following printf() added by Stephen Williams */
printf("\nadding %s\n", objname);
/*
* Open the object file
* Changed by Stephen Williams to use stdio streams
*/
objfp = fopen(objname, "r");
if (!objfp) {
fprintf(stderr, "%s cannot be added\nAlib abandoned\n", objname);
exit(1);
}
/*
* Allocate a node to hold the file.
*/
lp = (LL *)getmem(sizeof(LL));
if (lp == NULL) {
fprintf(stderr, "Not enough memory.\nAlib abandoned\n");
exit(1);
}
/*
* Initialize it.
*
* Changes by Stephen Williams; the naughty author used absolute
* values for his lseek() modes; not SEEK_SET and SEEK_END.
* This was very very very silly. Corrected
*
* Additional change; lseek() changed to fseek(), because I'm using
* stdio streams, not Unix file descriptors
*/
strcpy(lp->dir_entry.object_filename, objname);
fseek(objfp, 0, SEEK_END);
lp->dir_entry.module_size = ftell(objfp);
/* %d in following printf() changed to %ld by Stephen Williams */
printf("module size = %ld\n", lp->dir_entry.module_size);
fseek(objfp, 0, SEEK_SET);
/*
* Allocate the buffer to read the object module into.
*/
lp->object_module = getmem(lp->dir_entry.module_size);
if (lp->object_module == NULL) {
fprintf(stderr, "Not enough memory.\nAlib abandoned\n");
exit(1);
}
/*
* Read in the file.
*/
if (fread(lp->object_module, lp->dir_entry.module_size, 1, objfp) != 1) {
fprintf(stderr, "Library file is corrupted.\nAlib abandoned\n");
exit(1);
}
/*
* Add module to linked list.
*/
lp->next = objlist;
objlist = lp;
/*
* Close object file and return.
*/
fclose(objfp);
printf("%s added\n", name);
}
/*
* The following routine writes the library from memory and exits.
*
* K&R-style function definition changed to ANSI-style by Stephen Williams
*/
void close_library(void) {
LL *lp;
long file_position;
long length;
/*
* Open the library
*
* +++ Changes by Stephen Williams +++
*
* All I/O changed from Unix-style to stdio streams;
*
* - Spelling mistake in error strings corrected; "openning"
* changed to "opening"
*
*/
libfp = fopen(libname, "w");
if (!libfp) {
fprintf(stderr, "Error opening %s for output\nAlib abandoned", libname);
exit(1);
}
dirfp = fopen(dirname, "w");
if (!dirfp) {
fprintf(stderr, "Error opening %s for output\nAlib abandoned", dirname);
exit(1);
}
/*
* Write out the individual modules and directory records.
*/
file_position = 0;
for (lp = objlist; lp != NULL; lp = lp->next) {
length =
fwrite(lp->object_module, 1, lp->dir_entry.module_size, libfp);
if (length != lp->dir_entry.module_size) {
fprintf(stderr, "Error writing to library file\nAlib abandoned\n");
exit(1);
}
lp->dir_entry.module_offset = file_position;
file_position += length;
if (fwrite((char *)&lp->dir_entry, sizeof(LD), 1, dirfp) != 1) {
fprintf(stderr, "Error writing to directory file\nAlib abandoned\n");
exit(1);
}
}
/*
* Close the library files
*/
fclose(libfp);
fclose(dirfp);
/* the SetProtection() lines added by Stephen Williams */
#ifdef AMIGA
SetProtection(libname, FIBF_EXECUTE);
SetProtection(dirname, FIBF_EXECUTE);
#endif
/* the word "Library" in the following string capitalized by
Stephen Williams. Initial \n also added */
printf("\nLibrary is %ld bytes\nAlib complete\n", file_position);
exit(0);
}
/*
* K&R-style function definition changed to ANSI-style by Stephen Williams
*
* This function was below main(); moved above so main() sees a
* declaration for it
*/
void directory(void) {
LD d_entry;
int count;
int bytes;
/* Change by Stephen Williams: Unix I/O changed to stdio streams */
dirfp = fopen(dirname, "r");
if (!dirfp) {
fprintf(stderr, "%s not found\n", dirname);
exit(1);
}
printf("Directory of library %s\n", libname);
printf("Module Name Size Offset\n");
count = bytes = 0;
while (fread((char *)&d_entry, sizeof(LD), 1, dirfp) == 1) {
/* %ds in following printf() changed to %lds by Stephen Williams */
printf("%-30.30s %-6ld %-6ld\n", d_entry.object_filename,
d_entry.module_size, d_entry.module_offset);
count++;
bytes += d_entry.module_size;
}
printf("Library consists of %d entries totalling %d bytes\n", count,
bytes);
fclose(dirfp);
}
/*
* Main program.
*
* K&R-style function definition changed to ANSI-style by Stephen Williams
*/
int main(int argc, char * argv[])
{
int count;
/*
* Banner changed by Stephen Williams to reflect the fact that the
* program has been hacked around
*/
printf("Alib 1.0sw1\n"
"Amiga Object Module Librarian\n"
"Programmed by Mike Schwartz\n"
"Altered by Stephen Williams, without permission\n"
"(C)1985 MS Software, all rights reserved\n\n");
/*
* check for command line parameters present.
*/
if (argc < 3)
help();
/*
* setup the option and filenames
*/
option = argv[1][0];
strcpy(libname, argv[2]);
strcpy(dirname, argv[2]);
/*
* start of major change by Stephen Williams
*/
/* .lib extension present? */
if(!strcmp((char *)(libname + strlen(libname) - 4), ".lib"))
/* Yes; replace .lib with .dir in other name */
strcpy((char *)(dirname + strlen(dirname) - 3), "dir");
else {
/* Nope, gotta add it */
strcat(libname, ".lib");
strcat(dirname, ".dir");
}
/*
* end of change by Stephen Williams
*/
if (option == 'l' || option == 'L') {
directory();
exit(0);
}
if (option != 'd' && option != 'D' && option != 'r' && option != 'R')
help();
/*
* Open the library file
*/
open_library();
for (count = 3; count < argc; count++) {
switch(option) {
case 'd':
case 'D':
/* message format changed by Stephen Williams */
printf("\nDeleting %s from library...\n", argv[count]);
if (!kill_module(argv[count])) {
printf("failed\n");
fprintf(stderr, "%s not defined in library\n", argv[count]);
} else
printf("done\n");
break;
case 'r':
case 'R':
kill_module(argv[count]);
add_module(argv[count]);
break;
}
}
close_library();
}